module.exports = {
  code: {
    dependency: ["const {Operator, BoolOperation} = require('types');"],
  },
  lex: {
    macros: {
      digit: '[0-9]',
      esc: '\\\\',
      int: '-?(?:[0-9]|[1-9][0-9]+)',
      exp: '(?:[eE][-+]?[0-9]+)',
      frac: '(?:\\.[0-9]+)',
    },
    rules: [
      ['\\s+', '/* skip whitespace */'],
      ['{int}{frac}?{exp}?\\b', "return 'NUMBER';"],
      ['in(?=[\\s\\[])', "return 'in'"],
      ['not(?=\\s)', "return 'not'"],
      ['FULL', "return 'FULL'"],
      ['EMPTY', "return 'EMPTY'"],
      ['[a-zA-Z_][a-zA-Z0-9_]*', "return 'STRING';"],
      ['\\(', "return '('"],
      ['\\)', "return ')'"],
      ['\\[', "return '['"],
      ['\\]', "return ']'"],
      [',', "return ','"],
      ['&&', "return '&&'"],
      ['\\|\\|', "return '||'"],
      ['<=', "return '<='"],
      ['>=', "return '>='"],
      ['<', "return '<'"],
      ['>', "return '>'"],
      ['!=', "return '!='"],
      ['==', "return '=='"],
      ['~', "return '~'"], // 属于
      ['$', "return 'EOF'"],
    ],
  },

  start: 'expressions',

  operators: [
    ['left', '||'],
    ['left', '&&'],
  ],

  bnf: {
    BaseType: [
      ['STRING', '$$ = yytext'],
      ['NUMBER', '$$ = Number(yytext)'],
    ],

    ElementList: [
      ['BaseType', '$$ = [$1]'],
      ['ElementList , BaseType', '$$ = $1; $1.push($3)'],
    ],

    ItemArray: [
      ['[ ]', '$$ = []'],
      ['[ ElementList ]', '$$ = $2'],
    ],

    ValueType: [
      ['BaseType', '$$ = $1;'],
      ['ItemArray', '$$ = $1;'],
    ],

    BoolItem: [
      ['FULL', '$$ = {key: "not_matter", operator: Operator.FULL, value: 0}'],
      ['EMPTY', '$$ = {key: "not_matter", operator: Operator.EMPTY, value: 0}'],
      ['STRING == ValueType', '$$ = {key: $1, operator: Operator.EQ, value: $3}'],
      ['STRING != ValueType', '$$ = {key: $1, operator: Operator.NEQ, value: $3}'],
      ['STRING in ItemArray', '$$ = {key: $1, operator: Operator.IN, value: $3}'],
      ['STRING not in ItemArray', '$$ = {key: $1, operator: Operator.NOT_IN, value: $4}'],
      ['STRING < BaseType', '$$ = {key: $1, operator: Operator.LT, value: $3}'],
      ['STRING > BaseType', '$$ = {key: $1, operator: Operator.GT, value: $3}'],
      ['STRING >= BaseType', '$$ = {key: $1, operator: Operator.NLT, value: $3}'],
      ['STRING <= BaseType', '$$ = {key: $1, operator: Operator.NGT, value: $3}'],
      ['STRING ~ [ NUMBER , NUMBER ]', '$$ = {key: $1, operator: Operator.RIN, value: [Number( $4 ), Number($6)]}'],
      [
        'STRING ~ ( NUMBER , NUMBER ]',
        '$$ = {key: $1, operator: Operator.LO_IN_INNER, value: [Number( $4 ), Number($6)]}',
      ],
      [
        'STRING ~ [ NUMBER , NUMBER )',
        '$$ = {key: $1, operator: Operator.RO_IN_INNER, value: [Number( $4 ), Number($6)]}',
      ],
      [
        'STRING ~ ( NUMBER , NUMBER )',
        '$$ = {key: $1, operator: Operator.O_IN_INNER, value: [Number( $4 ), Number($6)]}',
      ],
    ],

    CombinedItem: [
      ['( BoolItem )', '$$ = $2'],
      ['( CombinedItem )', '$$ = $2'],

      ['BoolItem || CombinedItem', '$$ = {operator: BoolOperation.OR, args: [$1, $3]}'],
      ['BoolItem && CombinedItem', '$$ = {operator: BoolOperation.AND, args: [$1, $3]}'],

      ['CombinedItem || BoolItem', '$$ = {operator: BoolOperation.OR, args: [$1, $3]}'],
      ['CombinedItem && BoolItem', '$$ = {operator: BoolOperation.AND, args: [$1, $3]}'],

      ['CombinedItem && CombinedItem', '$$ = {operator: BoolOperation.AND, args: [$1, $3]}'],

      ['BoolItem && BoolItem', '$$ = {operator: BoolOperation.AND, args: [$1, $3]}'],
      ['BoolItem || BoolItem', '$$ = {operator: BoolOperation.OR, args: [$1, $3]}'],
    ],

    expressions: [
      // ['BoolItem EOF', 'console.log(JSON.stringify($1, null, 2)); return $1;'],
      // ['CombinedItem EOF', 'console.log(JSON.stringify($1, null, 2)); return $1;'],
      ['BoolItem EOF', 'return $1;'],
      ['CombinedItem EOF', 'return $1;'],
    ],
  },
};


